﻿using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using FreeRedis;
using Masuit.Tools;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using sixgod.Enum.System;

namespace sixgod.Common
{
    public class JwtHelper
    {
        private readonly IConfiguration _configuration;
        private readonly RedisClient _redisClient;
        private const string _cacheKey = CacheKeyConsts.SYSTEM_LIST;
        private readonly string SecurityKey;
        private readonly string RefreshKey;
        private readonly JwtSecurityTokenHandler handler;
        /// <summary>Initializes a new instance of the <see cref="T:System.Object" /> class.</summary>
        public JwtHelper(IConfiguration configuration, IMemoryCache cache, RedisClient redisClient)
        {
            _configuration = configuration;
            _redisClient = redisClient;

            SecurityKey = _configuration["Jwt:SecurityKey"];
            RefreshKey = _configuration["Jwt:RefreshKey"];
            handler = new JwtSecurityTokenHandler();
        }

        /// <summary>
        /// 生成jwt
        /// </summary>
        /// <param name="claims"></param>
        /// <returns></returns>
        public string CreateJwt(Claim[] claims)
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
            issuer: "sixgod.sso",
            audience: "",
            claims: claims,
            notBefore: DateTime.Now,
            expires: DateTime.Now.AddHours(1),
            signingCredentials: creds);

            return handler.WriteToken(token);
        }

        /// <summary>
        /// 生成刷新令牌
        /// </summary>
        /// <returns></returns>
        public string CreateRefreshToken(Claim[] claim)
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(RefreshKey));
            var guid = Guid.NewGuid().ToString();

            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            
            var claims = new List<Claim>
            {
                new Claim("tokenId",guid),
            };
            claims.AddRange(claim);

            var token = new JwtSecurityToken("sixgod.sso", "", claims, DateTime.UtcNow, DateTime.UtcNow.AddDays(1), creds);

            return handler.WriteToken(token);
        }

        /// <summary>
        /// 校验认证jwt状态
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task<(JwtVailResut, IEnumerable<Claim>)> DeCodeAccessToken(string token)
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey));

            var validateParameter = new TokenValidationParameters()
            {
                ValidateLifetime = true,
                ValidateIssuer = true,
                IssuerSigningKey = key
            };

            try
            {
                //校验并解析token
               var result = await handler.ValidateTokenAsync(token,validateParameter);
               // todo 考虑是否添加其他验证直接在这里面

               return (JwtVailResut.Success,result.ClaimsIdentity.Claims);
            }
            catch (SecurityTokenExpiredException)
            {
                //表示过期
                return (JwtVailResut.Expired,null)!;
            }
            catch (SecurityTokenException)
            {
                //表示token错误
                return (JwtVailResut.Error,null)!;
            }
            
        }

        /// <summary>
        /// 校验刷新jwt状态
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task<(JwtVailResut, IEnumerable<Claim>)> DeCodeRefreshToken(string token)
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(RefreshKey));

            var validateParameter = new TokenValidationParameters()
            {
                ValidateLifetime = true,
                ValidateIssuer = true,
                IssuerSigningKey = key
            };

            try
            {
                //校验并解析token
               var result = await handler.ValidateTokenAsync(token,validateParameter);
               // todo 考虑是否添加其他验证直接在这里面

               return (JwtVailResut.Success,result.ClaimsIdentity.Claims);
            }
            catch (SecurityTokenExpiredException)
            {
                //表示过期
                return (JwtVailResut.Expired,null)!;
            }
            catch (SecurityTokenException)
            {
                //表示token错误
                return (JwtVailResut.Error,null)!;
            }
            
        }
    }
}
